﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace zijian666.DI;

[TestClass]
public class 多生命周期注入测试
{
    [TestMethod]
    public void 没有瞬态服务()
    {
        var services = new ServiceCollection()
            .AddComponents()
            .AddAutowired()
            .BuildServiceProvider();
        using (var scope = services.CreateScope())
        {
            var a = services.GetService<MyClass>();
            var b = scope.ServiceProvider.GetService<MyClass>();
            var c = services.GetService<MyClass>();
            var d = scope.ServiceProvider.GetService<MyClass>();
            Assert.AreNotEqual(a, b);
            Assert.AreEqual(a, c);
            Assert.AreEqual(b, d);


            Assert.IsTrue(a.IsRoot);
            Assert.IsFalse(b.IsRoot);
        }
    }


    [TestMethod]
    public void 多类型没有瞬态服务()
    {
        var services = new ServiceCollection()
            .AddComponents()
            .BuildServiceProvider();
        using (var scope = services.CreateScope())
        {
            var a = services.GetService<MyClass>();
            var b = scope.ServiceProvider.GetService<MyClass>();
            var c = services.GetService<MyClass>();
            var d = scope.ServiceProvider.GetService<MyClass>();
            Assert.AreNotEqual(a, b);
            Assert.AreEqual(a, c);
            Assert.AreEqual(b, d);


            var a1 = services.GetService<MyClass1>();
            var b1 = scope.ServiceProvider.GetService<MyClass1>();
            var c1 = services.GetService<MyClass1>();
            var d1 = scope.ServiceProvider.GetService<MyClass1>();
            Assert.AreNotEqual(a1, b1);
            Assert.AreEqual(a1, c1);
            Assert.AreEqual(b1, d1);

            Assert.AreEqual(a, a1);
        }
    }

    [DebuggerDisplay("{Id}")]
    class MyClass(IServiceProvider services)
    {
        private static long _id = 0;
        public long Id { get; } = Interlocked.Increment(ref _id);
        public IServiceProvider Services { get; } = services;

        public bool IsRoot
        {
            get
            {
                var x = Services.GetService<SingletonServiceProvider>();
                return Services == x.GetService<IServiceProvider>();
            }
        }
    }

    [SingletonComponent]
    [ScopedComponent]
    [SingletonComponent(typeof(MyClass))]
    [ScopedComponent(typeof(MyClass))]
    class MyClass1(IServiceProvider services) : MyClass(services);


    [TestMethod]
    public void 有瞬态服务()
    {
        // 如果有瞬态服务，则每次获取的都是新的实例, 单例和范围实例没有意义
        var services = new ServiceCollection()
            .AddComponents()
            .AddAutowired()
            .BuildServiceProvider();
        using (var scope = services.CreateScope())
        {
            var a = services.GetService<MyTransient>();
            var b = scope.ServiceProvider.GetService<MyTransient>();
            var c = services.GetService<MyTransient>();
            var d = scope.ServiceProvider.GetService<MyTransient>();
            Assert.AreNotEqual(a, b);
            Assert.AreNotEqual(a, c);
            Assert.AreNotEqual(a, d);
            Assert.AreNotEqual(b, c);
            Assert.AreNotEqual(b, d);
            Assert.AreNotEqual(c, d);


            Assert.IsTrue(a.IsRoot);
            Assert.IsTrue(c.IsRoot);
            Assert.IsFalse(b.IsRoot);
            Assert.IsFalse(d.IsRoot);
        }
    }


    [SingletonComponent]
    [ScopedComponent]
    [TransientComponent]
    [DebuggerDisplay("{Id}")]
    class MyTransient(IServiceProvider services)
    {
        private static long _id = 0;
        public long Id { get; } = Interlocked.Increment(ref _id);
        public IServiceProvider Services { get; } = services;

        public bool IsRoot
        {
            get
            {
                var x = Services.GetRequiredService<SingletonServiceProvider>();
                return Services == x.GetService<IServiceProvider>();
            }
        }
    }
}
